package com.itita.ww2.utils;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.smartfoxserver.v2.entities.data.ISFSObject;
import com.smartfoxserver.v2.entities.data.SFSArray;
import com.smartfoxserver.v2.entities.data.SFSObject;
import com.thoughtworks.xstream.XStream;

import okio.BufferedSink;
import okio.BufferedSource;
import okio.Okio;
import okio.Sink;
import okio.Source;

/**
 * 文件操作工具类
 * @author Lan
 * 
 */
public class FileUtils {
	private static final Logger logger = LoggerFactory.getLogger(FileUtils.class.getName());

	/**
	 * 将一个bean写入到文件中
	 * @param t bean
	 * @param path 文件路径
	 */
	public static final <T extends Object> void beanToXMLFile(T t, String path) {
		XStream xstream = new XStream();
		xstream.autodetectAnnotations(true);
		xstream.processAnnotations(t.getClass());
		String xml = xstream.toXML(t);
		writeStringToFile(xml, path);
	}

	/**
	 * 写入一个str(UTF-8)到path
	 * @param str
	 * @param path
	 */
	public static final void writeStringToFile(String str, String path) {
		BufferedSink bs = null;
		try {
			File file = new File(path);
			if (!file.getParentFile().exists()) {
				file.getParentFile().mkdirs();
			}
			if (!file.exists()) {
				// file.c
				file.createNewFile();
			}
			Sink sink = Okio.sink(file);
			bs = Okio.buffer(sink);
			bs.writeUtf8(str);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (bs != null) {
				try {
					bs.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	/**
	 * 读取指定位置的配置文件,并转换为指定的Bean
	 * @param path
	 * @param t Bean类型
	 * @return Bean对象
	 * @Usege Bean b = readConfToBean("file/xx.xml",Bean.class);
	 */
	@SuppressWarnings("unchecked")
	public static final <T extends Object> T readConfToBean(String path, Class<?> t) {
		// logger.info("Loading " + path);
		XStream xstream = new XStream();
		xstream.autodetectAnnotations(true);
		xstream.processAnnotations(t);
		InputStream is = readFileToInputStream(path);
		if (is == null) {
			logger.error("file not found");
			return null;
		}
		T obj = (T) xstream.fromXML(is);
		return obj;
	}

	/**
	 * 读取一个文件并转换为 InputStream (使用Okio库)
	 * @param path
	 * @return InputStream
	 */
	public static final InputStream readFileToInputStream(String path) {
		InputStream is = null;
		try {
			File file = new File(path);
			Source source = Okio.source(file);
			BufferedSource bs = Okio.buffer(source);
			is = bs.inputStream();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
		return is;
	}

	/**
	 * 使用Okio读取文件为String
	 * 
	 * @param file full-path
	 * @return content
	 */

	public static final String readFileAsString(String path) {
		String content = null;
		BufferedSource bs = null;
		try {
			File file = new File(path);
			Source source = Okio.source(file);
			bs = Okio.buffer(source);
			content = bs.readUtf8();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (bs != null) {
				try {
					bs.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return content;
	}

	/**
	 * 使用Okio读取文件为String
	 * 
	 * @param file file
	 * @return content
	 */
	public static final String readFileAsString(File file) {
		String content = null;
		BufferedSource bs = null;
		try {
			Source source = Okio.source(file);
			bs = Okio.buffer(source);
			content = bs.readUtf8();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (bs != null) {
				try {
					bs.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return content;
	}

	/**
	 * 读取目录中的所有文件,若目录不存在,则创建目录
	 * @param folderPath
	 * @return
	 */
	public static final File[] readFilesFromFolder(String folderPath) {
		File file = new File(folderPath);
		if (!file.exists()) {
			file.mkdir();
		}
		if (file.isDirectory()) {
			return file.listFiles();
		} else {
			logger.error("Path: " + folderPath + " is not a directory!");
			return null;
		}
	}

	public static enum ValueType {
		String, Array, Object
	}

	/**
	 * 读取某文件夹内所有文件 AS ISFSObject (key-filename,value-valuetype)
	 * @param folderPath
	 * @param valueType
	 * @return
	 */
	public static final ISFSObject readSFSObjectFromFolder(String folderPath, ValueType valueType) {
		ISFSObject obj = new SFSObject();
		for (File file : readFilesFromFolder(folderPath)) {
			if (file.isDirectory()) {
				continue;
			}
			String key = file.getName().substring(0, file.getName().indexOf("."));

			String value = readFileAsString(file);
			switch (valueType) {
			case String:
				obj.putUtfString(key, value);
				break;
			case Array:
				obj.putSFSArray(key, SFSArray.newFromJsonData(value));
				break;
			case Object:
				obj.putSFSObject(key, SFSObject.newFromJsonData(value));
				break;
			default:
				break;
			}
			// logger.info("file: " + key + " load success! AS " + valueType.toString());
		}
		return obj;
	}

	/**
	 * 读取单个配置文件,其中内部结构为
	 * filename : value (key : value)
	 * @param path
	 * @param valueType
	 * @return
	 */
	public static final ISFSObject readSFSObjectFromFile(String path, ValueType valueType) {
		File file = new File(path);
		if (!file.exists()) {
			logger.error("File: " + path + " hasn't exists!");
			return null;
		}
		if (file.isFile()) {
			ISFSObject obj = new SFSObject();
			String key = file.getName().substring(0, file.getName().indexOf("."));
			String value = readFileAsString(file);
			switch (valueType) {
			case String:
				obj.putUtfString(key, value);
				break;
			case Array:
				obj.putSFSArray(key, SFSArray.newFromJsonData(value));
				break;
			case Object:
				obj.putSFSObject(key, SFSObject.newFromJsonData(value));
				break;
			}
			return obj;
		} else {
			logger.error("Path: " + path + " not a file.");
			return null;
		}
	}

	/**
	 * 从文件中获取email内容并对内容中的 EL表达式 进行替换
	 * 
	 * @param full file path
	 * @param fields key-value 		${key}<-value
	 * @return replaced file content
	 */
	public static final String getEmailMessage(String path, Map<String, String> fields) {
		String result = readFileAsString(path);
		for (Map.Entry<String, String> val : fields.entrySet()) {
			result = replaceEL(result, val.getKey(), val.getValue());
		}
		return result;
	}

	/**
	 * 使用正则替换EL表达式 ${url} ${.....} 诸如此类
	 * 
	 * @param key
	 * @param value
	 * @return
	 */
	private static final String replaceEL(String str, String key, String value) {
		String pattern = "\\$\\s{0,1}\\{\\s{0,1}" + key + "\\s{0,1}\\}";
		return str.replaceAll(pattern, value);
	}
}
